package top.lyjwn.todo.common.code;

import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.lyjwn.todo.common.redis.RedisMap;
import top.lyjwn.todo.common.template.R;
import top.lyjwn.todo.common.utils.RandomValue;
import top.lyjwn.todo.mail.SenderHelper;
import top.lyjwn.todo.mail.data.MailContentTypeEnum;
import top.lyjwn.todo.mail.error.MailException;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Component
public class EmailVCode {

    @Autowired
    private RedisMap redisMap;

    private long EXPIRES_TIME = 2 * 60 * 1000;


    private final Logger log = LoggerFactory.getLogger("error");

    private ExecutorService sendExecutor = new ThreadPoolExecutor(1, 4, 5, TimeUnit.SECONDS, new LinkedTransferQueue<Runnable>());


    /**
     * 验证->验证码
     *
     * @param mail
     * @param vcode
     * @return
     */
    public R verifyVCode(String mail, String vcode) {

        return verifyVCode(null, null, mail, vcode);
    }


    /**
     * 验证->验证码
     *
     * @param module
     * @param mail
     * @param vcode
     * @return
     */
    public R verifyVCode(String module, String mail, String vcode) {
        return verifyVCode(module, null, mail, vcode);
    }

    /**
     * 验证->验证码
     *
     * @param module 功能模块
     * @param userId 用户id
     * @param mail   验证码标识符
     * @return
     */
    public R verifyVCode(String module, String userId, String mail, String vcode) {
        String key = builderKey(module, userId, mail);
        // 查询验证码
        String code = getCodeVal(key);
        // 清除验证码
        delVCode(key);
        if (StringUtils.isBlank(code)) {
            return R.init().error(500, "验证码已过期");
        }
        if (StringUtils.isBlank(vcode) || !vcode.equalsIgnoreCase(code)) {
            return R.init().error(500, "验证码错误");
        }
        return R.init().ok("验证码通过");
    }

    /**
     * 生成验证码
     *
     * @return
     */
    public R generateVCode(String mail) {
        return generateVCode(null, mail);
    }

    /**
     * 生成验证码
     *
     * @param module 功能模块
     * @return
     */
    public R generateVCode(String module, String mail) {
        return generateVCode(module, null,mail);
    }

    /**
     * 生成验证码
     *
     * @param module 功能模块
     * @param userId 用户id
     * @return
     */
    public R generateVCode(String module, String userId, String mail) {
        // 随机的数字字符串
        String randomNumberString = RandomValue.getRandomNumberString(6);
        if (module != null && userId != null) {
            saveVCode(module, userId, mail, randomNumberString);
        } else if (module != null && userId == null) {
            saveVCode(module, mail, randomNumberString);
        } else {
            saveVCode(mail, randomNumberString);
        }

        // 发送邮箱
        List<String> mail_str = new ArrayList<>();
        mail_str.add(mail);
        //构造结果
        sendExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    new SenderHelper()
                            .title("邮箱验证码")
                            .content(randomNumberString)
                            .contentType(MailContentTypeEnum.TEXT)
                            .targets(mail_str).send();
                } catch (MailException e) {
                    log.error( "发送邮件失败  邮箱:"+mail,e);
                }
            }
        });
        return R.init().ok("已下发邮件至"+mail+",请注意查收");
    }

    /**
     * 删除验证码
     *
     * @param key
     */
    private void delVCode(String key) {
        redisMap.delete(key);
    }

    /**
     * 获得验证码
     *
     * @param key
     */
    private String getCodeVal(String key) {
        Object o = redisMap.get(key);
        if (o != null) {
            return o.toString();
        } else {
            return null;
        }
    }


    /**
     * 保存验证码
     *
     * @param uuid
     * @param vcode
     */
    private void saveVCode(String uuid, String vcode) {
        String key = builderKey(null, null, uuid);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(key,vcode);
        redisMap.set(key, jsonObject, EXPIRES_TIME);
    }

    /**
     * 保存验证码
     *
     * @param module 功能模块
     * @param uuid
     * @param vcode
     */
    private void saveVCode(String module, String uuid, String vcode) {
        String key = builderKey(module, null, uuid);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(key,vcode);
        redisMap.set(key, jsonObject, EXPIRES_TIME);
    }


    /**
     * 保存验证码
     *
     * @param module 功能模块
     * @param userId 用户id
     * @param uuid
     * @param vcode
     */
    private void saveVCode(String module, String userId, String uuid, String vcode) {
        String key = builderKey(module, userId, uuid);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(key,vcode);
        redisMap.set(key, jsonObject, EXPIRES_TIME);
    }


    /**
     * 构造redis键
     *
     * @param module
     * @param userId
     * @param uuid
     * @return
     */
    private String builderKey(String module, String userId, String uuid) {
        StringBuilder key = new StringBuilder("mailVCode:");
        if (module != null && userId != null) {
            key.append(module).append(":").append(userId).append(":").append(uuid);
        } else if (module != null) {
            key.append(module).append(":").append(uuid);
        } else {
            key.append(":").append(uuid);
        }
        return key.toString();
    }

}
